﻿using System;
using System.Security.Principal;
using System.Threading;
using System.Web;
using System.Web.Security;

namespace SubSonic.Security{
    public class SubSonicSecurityModule : IHttpModule {
        public void Dispose(){
        }

        public void Init(System.Web.HttpApplication context){
            context.PostAuthenticateRequest += OnPostAuthenticateRequest;
        }

        private void OnPostAuthenticateRequest(object sender, EventArgs e){
            // Ensure that the user principal is put back where it belongs on every request.
            HttpApplication context = (HttpApplication)sender;
            IPrincipal principal = GetPrincipal(context);
            HttpContext.Current.User = principal;
            Thread.CurrentPrincipal = principal;
        }

        private IPrincipal GetPrincipal(HttpApplication context){
            IPrincipal principal = null;

            //pull the passwordFormat out of cookie
            MembershipPasswordFormat passwordFormat = MemProviderConfig.ConvertToFormat(context.Request.Cookies[Helper.Cookies.cookiePasFormat].Value);

            string userName = context.User.Identity.Name;
            bool cacheUserInfo = Convert.ToBoolean(context.Request.Cookies[Helper.Cookies.cookieCacheUser].Value);

            if (cacheUserInfo && HttpContext.Current.Cache["ss_User_" + userName] != null)
                principal = (IPrincipal)HttpContext.Current.Cache["ss_User_" + userName];
            else{
                //validate user from cookie values
                string password = context.Request.Cookies[Helper.Cookies.cookiePassword].Value;
                principal = SubSonic.Security.SubSonicPrincipal.ValidateUser(userName, password, passwordFormat);
                if (principal == null)
                    principal = SubSonic.Security.SubSonicPrincipal.UnauthenticatedUser();

                if (cacheUserInfo)
                    HttpContext.Current.Cache["ss_User_" + userName] = principal;

            }

            return principal;
        }
    }
}

